
#ifndef RCRESPTR_H_
#define RCRESPTR_H_

#include <wild/RCResourcePtrHolder.h>
#include <wild/WildConfig.h>


namespace wild
{


template <class ResourceType>
class RCResPtr
{
public:
    RCResPtr(const RCResPtr<ResourceType> & resPtr);
    explicit RCResPtr(ResourceType * pRes);

    RCResPtr(wild::RCResourcePtrHolder* pHolder = 0);

    virtual ~RCResPtr();

	RCResPtr<ResourceType> & operator= (const RCResPtr<ResourceType> & resPtr);

    ResourceType * operator->() const { return static_cast<ResourceType *>((ResourceType *)m_pResHolder->pRes); }
    ResourceType & operator*() const { return *(static_cast<ResourceType *>((ResourceType *)m_pResHolder->pRes)); }

    bool operator==(RCResPtr<ResourceType> res) const;
    bool operator!=(RCResPtr<ResourceType> res) const { return !operator==(res); }
    bool operator< (RCResPtr<ResourceType> res) const;


    RCResourcePtrHolder * GetResPtrHolder() const { return m_pResHolder; }
    typedef ResourceType * PointerType;

private:
    wild::RCResourcePtrHolder* m_pResHolder;
};


template <class ResourceType>
RCResPtr<ResourceType>::RCResPtr(const RCResPtr<ResourceType> & resPtr)
{
    m_pResHolder = resPtr.GetResPtrHolder();
    if (m_pResHolder != 0)
        m_pResHolder->AddRef();    
}


template <class ResourceType>
RCResPtr<ResourceType>::RCResPtr(ResourceType * pRes)
{
    m_pResHolder = new RCResourcePtrHolder(pRes); 
    m_pResHolder->AddRef();    
}

template <class ResourceType>
RCResPtr<ResourceType>::RCResPtr(RCResourcePtrHolder * pHolder) 
:m_pResHolder(pHolder)
{
	if(m_pResHolder == 0)
	{		        		
				
		ResourceType* pRes_ = new ResourceType;
		m_pResHolder = new RCResourcePtrHolder((IResource*)pRes_);
		
	}
    
	m_pResHolder->AddRef();
}


template <class ResourceType>
RCResPtr<ResourceType>::~RCResPtr()
{
    if (m_pResHolder != 0)
	{
        int i = m_pResHolder->Release(); 
		//int a = i;
		/*if(i<=0)
			SAFE_DELETE(m_pResHolder);*/
		//TRACE("observer release address=%x refcnt=%d\n",(DWORD)m_pResHolder,i);
		
	}
}


template <class ResourceType>
RCResPtr<ResourceType> & RCResPtr<ResourceType>::operator= (const RCResPtr<ResourceType> & resPtr)
{
    if (m_pResHolder != resPtr.GetResPtrHolder())
    {
        if (m_pResHolder != 0)
		{
            int i = m_pResHolder->Release(); 
			/*if(i<=0)
				SAFE_DELETE(m_pResHolder);*/
			//TRACE("observer release address=%x refcnt=%d\n",(DWORD)m_pResHolder,i);
		}
        m_pResHolder = resPtr.GetResPtrHolder();
        if (m_pResHolder != 0)
            m_pResHolder->AddRef();    
    }
    return *this;
}



template <class ResourceType>
bool RCResPtr<ResourceType>::operator==(RCResPtr<ResourceType> res) const
{
    if (m_pResHolder == res.m_pResHolder)
        return true;
    // At this point, both holders cannot be NULL
    if (res.m_pResHolder == 0 && m_pResHolder->pRes == 0)
        return true;
    if (m_pResHolder == 0 && res.m_pResHolder->pRes == 0)
        return true;
    if (m_pResHolder != 0 && res.m_pResHolder != 0 &&
        m_pResHolder->pRes == res.m_pResHolder->pRes)
        return true;
    return false;
}


template <class ResourceType>
bool RCResPtr<ResourceType>::operator< (RCResPtr<ResourceType> res) const
{
    if (res.m_pResHolder == 0)
        return false;
    if (m_pResHolder == 0)
        return true;
    return (m_pResHolder->pRes < res.m_pResHolder->pRes);
}


}	//	namespace wild



#endif 
